How to Structure Content for GitHub Copilot Instruction Files

tech
prompt-engineering
github-copilot
Learn how to create effective instruction files for GitHub Copilot with best practices for structure, scope, and limitations to ensure maximum reliability and avoid unwanted behaviors.
Author

Dario Airoldi

Published

December 11, 2025

How to Structure Content for GitHub Copilot Instruction Files

Instruction files (.instructions.md) are a powerful way to provide context-specific guidelines that automatically apply to files matching specific patterns.
Unlike prompt files (which are invoked on-demand) or agent files (which define persistent personas), instruction files work silently in the background, influencing Copilot’s behavior whenever you work with matching files.

This article explores how to structure instruction files effectively, understanding their limitations, and avoiding common pitfalls that can lead to unwanted bias, confusion, or distraction.

Table of Contents

🎯 Understanding Instruction Files

What Are Instruction Files?

Instruction files define coding standards, best practices, and contextual rules that automatically apply when working with specific files or file types. They’re stored in .github/instructions/ (workspace-level) or your VS Code user profile (user-level) and use glob patterns to determine when they activate.

Key Characteristics

Aspect Description
Extension .instructions.md
Activation Automatic based on applyTo pattern
Scope File/directory-specific or project-wide
Visibility Silent - not shown in chat but applied to context
Priority Combined with other instructions (no specific order guaranteed)
Tool Control None (relies on agent/prompt tool configuration)

When to Use Instruction Files

✅ Use instruction files for:

  • Coding standards - Language-specific conventions (e.g., Python PEP 8, C# naming conventions)
  • Framework guidelines - React component patterns, API design rules
  • Security requirements - Authentication checks, input validation rules
  • Documentation standards - Comment styles, README requirements
  • Build/test patterns - Test file structure, CI/CD requirements

❌ Don’t use instruction files for:

  • Task-specific workflows - Use prompt files instead (e.g., “generate component with tests”)
  • One-time operations - Use chat commands or inline chat
  • Persona definition - Use agent files instead (e.g., “security reviewer” role)
  • Complex multi-step processes - Use prompts or agents with workflow capabilities

📋 Instruction File Structure

File Format

Instruction files are Markdown documents with an optional YAML frontmatter header:

---
description: "Brief description of these instructions"
name: "Display name (defaults to filename)"
applyTo: "**/*.ts,**/*.tsx"
excludeAgent: "code-review"  # Optional: exclude from specific agents
---

# Instruction Body

Your coding standards and guidelines in Markdown format.

YAML Frontmatter Fields

Required Fields

None - all frontmatter is optional, but applyTo is highly recommended.

Optional Fields

Field Type Description Example
description String Brief description shown in UI "TypeScript coding standards"
name String Display name (defaults to filename without extension) "React Guidelines"
applyTo String Glob pattern(s) for file matching "**/*.py" or "**/*.ts,**/*.tsx"
excludeAgent String Exclude from specific agents: "code-review" or "coding-agent" "code-review"

ApplyTo Pattern Examples

Pattern Matches Example Files
**/*.py All Python files recursively src/main.py, tests/test_api.py
**/*.ts,**/*.tsx All TypeScript files components/Button.tsx, utils/helpers.ts
src/**/*.js JavaScript files under src/ src/app.js, src/utils/format.js
**/test_*.py Python test files anywhere tests/test_user.py, src/tests/test_api.py
docs/**/*.md Markdown files under docs/ docs/README.md, docs/api/endpoints.md
** All files (use sparingly) Everything in workspace

⚠️ Important: If applyTo is omitted, instructions are not applied automatically - you must attach them manually to chat requests.

Body Content

The instruction body contains your guidelines in Markdown format. This is where you define:

  • Coding standards: Naming conventions, formatting rules, code organization
  • Best practices: Security patterns, performance considerations, error handling
  • Framework-specific rules: Component structure, API design, testing patterns
  • Tool usage: Reference specific tools using #tool:<tool-name> syntax

Example structure:

---
applyTo: "**/*.tsx"
---

# React Component Guidelines

## Naming Conventions
- Use PascalCase for component names
- Use camelCase for props and handlers
- Prefix boolean props with `is`, `has`, or `should`

## Component Structure
- Functional components with TypeScript
- Props interface defined before component
- Hooks at the top of component body

## Example
```tsx
interface ButtonProps {
  label: string;
  onClick: () => void;
  isDisabled?: boolean;
}

export const Button: React.FC<ButtonProps> = ({ label, onClick, isDisabled = false }) => {
  return <button onClick={onClick} disabled={isDisabled}>{label}</button>;
};

Tool References

Use #tool:codebase to find similar components before creating new ones.


# ✍️ Writing Effective Instructions

## Core Principles

### 1. Be Specific and Concise

<mark>**Each instruction should be a single, clear statement**</mark>. Avoid vague guidelines that can be interpreted multiple ways.

**❌ Vague:**
```markdown
Write good code that follows best practices.

✅ Specific:

- Use descriptive variable names (minimum 3 characters, except loop counters)
- Always include error handling for async operations
- Add JSDoc comments for all exported functions

2. Focus on “How”, Not “Why”

Instructions should guide behavior, not explain rationale (unless the explanation is necessary for correct implementation).

❌ Too much explanation:

We use dependency injection because it makes code more testable and follows
SOLID principles. Dependency injection allows for better separation of concerns
and makes mocking easier during unit testing...

✅ Actionable guidance:

- Inject dependencies through constructor parameters
- Use interfaces for all injectable dependencies
- Register services in the DI container, not in constructors

3. Use Examples

Examples demonstrate correct usage and help Copilot understand the pattern you want.

## Error Handling Pattern

All API functions must include try-catch with proper error logging:

```typescript
async function fetchUser(id: string): Promise<User> {
  try {
    const response = await api.get(`/users/${id}`);
    return response.data;
  } catch (error) {
    logger.error('Failed to fetch user', { userId: id, error });
    throw new AppError('User fetch failed', { cause: error });
  }
}

### 4. Organize by Topic

<mark>Group related guidelines under clear headings</mark>. This improves readability and helps Copilot apply relevant rules.

```markdown
## Naming Conventions
- Classes: PascalCase
- Variables/Functions: camelCase
- Constants: UPPER_SNAKE_CASE

## File Organization
- One component per file
- Co-locate tests with source: `Button.tsx` + `Button.test.tsx`
- Keep utility functions in `utils/` directory

## Security
- Never commit secrets or API keys
- Sanitize all user input before database operations
- Use parameterized queries for SQL

5. Reference Tools When Appropriate

Use the #tool:<tool-name> syntax to guide Copilot to use specific capabilities:

## Before Creating New Components

Use #tool:codebase to search for similar existing components.
Use #tool:search to find component usage patterns.

Content Length Guidelines

Keep instruction files focused and concise. While there’s no hard token limit for individual instruction files, remember:

  • VS Code combines multiple instruction files when they match the current context
  • Instructions are added to every relevant chat request, consuming context window space
  • Long instructions dilute important guidelines by burying key points in detail

Recommended lengths:

Scope Recommended Length Example
Single language/framework 100-300 lines Python PEP 8 guidelines
Project-wide general rules 50-150 lines Company coding standards
Specific feature/pattern 30-100 lines API error handling pattern

⚠️ If instructions exceed 500 lines, consider splitting into multiple files with more specific applyTo patterns.

⚠️ Critical Limitations and Boundaries

Understanding what instruction files cannot do is just as important as knowing what they can do.

Technical Limitations

1. No Guaranteed Order

When multiple instruction files match the current context, VS Code combines them but no specific order is guaranteed. This means:

❌ Don’t write instructions that depend on order:

<!-- file: base-rules.instructions.md -->
Use the error handling pattern defined earlier.

<!-- file: api-rules.instructions.md -->
Here's the error handling pattern: [pattern details]

✅ Make each file self-contained:

<!-- file: base-rules.instructions.md -->
General coding rules...

<!-- file: api-rules.instructions.md -->
API Error Handling Pattern:
[complete pattern with examples]

2. Conflicts Are Non-Deterministic

If multiple instruction files provide conflicting guidance, Copilot’s choice is non-deterministic. Avoid potential conflicts between instructions.

❌ Conflicting instructions:

<!-- file: python-naming.instructions.md -->
Use snake_case for all function names.

<!-- file: api-naming.instructions.md -->
Use camelCase for API endpoint handlers.

✅ Resolve conflicts explicitly:

<!-- file: python-naming.instructions.md -->
applyTo: "**/*.py"
---
Use snake_case for function names, EXCEPT API handlers (use camelCase for those).

<!-- file: api-naming.instructions.md -->
applyTo: "**/api/**/*.py"
---
API endpoint handlers use camelCase to match JavaScript frontend conventions.

3. Instructions Are Always Applied (When Pattern Matches)

Instructions cannot be toggled on/off for specific chat requests. If the applyTo pattern matches the current file, the instructions are included.

This means:

  • ❌ Can’t temporarily disable instructions for experimentation
  • ❌ Can’t choose between different instruction “profiles”
  • ✅ Use more specific applyTo patterns to control when instructions apply
  • ✅ Use excludeAgent to exclude instructions from specific agents

4. No Tool Control

Instruction files cannot specify which tools are available (unlike prompts and agents). They rely on:

  • Default tools available to the current agent
  • Tool configuration in prompt files (if used)
  • Tool configuration in agent files (if active)

5. Silent Application

Instructions are not visible in chat - they’re silently added to the context. This can lead to:

  • ❌ Users unaware why Copilot generates code a certain way
  • ❌ Debugging confusion when unexpected patterns appear
  • ✅ Check References list in chat to see which instruction files were applied

Context Window Limitations

Every instruction file consumes part of the LLM’s context window. Be mindful of cumulative impact:

Context consumption example:

File Lines Tokens (approx) Pattern
general-rules.instructions.md 150 ~600 ** (all files)
python-pep8.instructions.md 200 ~800 **/*.py
react-patterns.instructions.md 180 ~720 **/*.tsx
api-security.instructions.md 120 ~480 **/api/**/*
Total (for a React + Python project) 650 ~2600

If you’re working on a .tsx file in the api/ directory, all four files could apply simultaneously, consuming ~2600 tokens before your actual prompt.

Best practices to manage context:

  1. Use specific patterns - Don’t use ** unless absolutely necessary
  2. Split by scope - Multiple focused files > one massive file
  3. Avoid duplication - Don’t repeat guidelines across files
  4. Review regularly - Remove outdated or unused instructions

🚫 Common Pitfalls and How to Avoid Them

Pitfall 1: Instructions Too Broad

Problem: Using applyTo: "**" causes instructions to apply to every file, even when inappropriate.

❌ Bad example:

---
applyTo: "**"
---
Always use async/await for asynchronous operations.
Always include unit tests.

This applies to configuration files, READMEs, scripts, etc., causing confusion.

✅ Solution: Be specific:

---
applyTo: "src/**/*.ts,src/**/*.tsx"
---
For TypeScript source files:
- Use async/await for asynchronous operations
- Include unit tests in co-located `.test.ts` files

Pitfall 2: Conflicting Instructions

Problem: Multiple instruction files give contradictory guidance for the same situation.

❌ Bad example:

<!-- python-general.instructions.md -->
Use single quotes for strings.

<!-- python-api.instructions.md -->
Use double quotes for strings to match JSON conventions.

✅ Solution: Resolve explicitly or use hierarchy:

<!-- python-general.instructions.md -->
applyTo: "**/*.py"
---
Use single quotes for strings, EXCEPT in API modules (use double quotes).

<!-- python-api.instructions.md -->
applyTo: "**/api/**/*.py"
---
API modules use double quotes for strings (matches JSON conventions).

Pitfall 3: Instructions Too Detailed

Problem: Overly verbose instructions consume context and dilute important rules.

❌ Bad example:

When writing functions in Python, you should always think about readability
because code is read more often than written. PEP 8 recommends...
[500 lines of explanations and history]

✅ Solution: Concise, actionable rules:

## Function Guidelines (PEP 8)
- Lowercase with underscores: `calculate_total()`
- Max line length: 79 characters
- Docstrings for all public functions
- Type hints for parameters and return values

Pitfall 4: Implicit Dependencies

Problem: Instructions reference concepts defined in other instruction files without repeating necessary context.

❌ Bad example:

<!-- file: advanced-patterns.instructions.md -->
Use the Repository Pattern defined in our base architecture.

If the base architecture file doesn’t apply to the current file, this instruction is confusing.

✅ Solution: Self-contained instructions:

<!-- file: advanced-patterns.instructions.md -->
Repository Pattern:
- All database access through repository interfaces
- Repository implementations in `repositories/` directory
- Example: `UserRepository` interface + `PostgresUserRepository` implementation

Pitfall 5: Instructions as Documentation

Problem: Using instruction files to document how things work rather than guide how to code.

❌ Bad example:

Our application uses a three-tier architecture. The presentation layer handles
HTTP requests, the business logic layer processes data, and the data access
layer interacts with databases. This pattern was chosen because...

✅ Solution: Focus on actionable guidance:

## Three-Tier Architecture Rules
- Controllers (presentation): Handle HTTP, no business logic
- Services (business logic): Pure functions, no database access
- Repositories (data access): Database operations only

Place files: `controllers/`, `services/`, `repositories/`

Pitfall 6: Overuse of Global Instructions

Problem: Repository-wide instructions (.github/copilot-instructions.md) become too large and apply to inappropriate contexts.

❌ Bad example:

<!-- .github/copilot-instructions.md - 2000 lines -->
Python rules...
JavaScript rules...
React patterns...
API security...
Database patterns...
[everything for every technology]

✅ Solution: Split into specific instruction files:

.github/
  copilot-instructions.md  # General project info (100 lines)
  instructions/
    python-standards.instructions.md       # applyTo: "**/*.py"
    react-patterns.instructions.md         # applyTo: "**/*.tsx"
    api-security.instructions.md           # applyTo: "**/api/**/*"
    database-patterns.instructions.md      # applyTo: "**/repositories/**/*"

🎨 Advanced Patterns

Pattern 1: Layered Instructions

Use multiple instruction files with increasingly specific patterns to create a hierarchy:

.github/instructions/
  general-code-quality.instructions.md        # applyTo: "**"
  backend-python.instructions.md              # applyTo: "backend/**/*.py"
  backend-api-endpoints.instructions.md       # applyTo: "backend/api/**/*.py"
  backend-api-auth.instructions.md            # applyTo: "backend/api/auth/**/*.py"

Each layer adds more specific guidance without duplicating rules from broader layers.

Pattern 2: Exclude Patterns for Edge Cases

Use multiple files with complementary patterns and excludeAgent to handle special cases:

<!-- standard-review.instructions.md -->
---
applyTo: "src/**/*.py"
excludeAgent: "code-review"  # Don't apply to manual reviews
---
Automated code standards (for coding agent only)...
<!-- manual-review-guidelines.instructions.md -->
---
applyTo: "src/**/*.py"
excludeAgent: "coding-agent"  # Don't apply to coding agent
---
Human reviewer guidelines (for code review only)...

Pattern 3: Technology-Specific Instructions

Organize by technology stack with precise glob patterns:

.github/instructions/
  frontend/
    react-components.instructions.md        # applyTo: "src/components/**/*.tsx"
    react-hooks.instructions.md             # applyTo: "src/hooks/**/*.ts"
    react-context.instructions.md           # applyTo: "src/contexts/**/*.tsx"
  backend/
    api-routes.instructions.md              # applyTo: "api/routes/**/*.py"
    database-models.instructions.md         # applyTo: "api/models/**/*.py"
    background-jobs.instructions.md         # applyTo: "api/jobs/**/*.py"

Pattern 4: Test-Specific Instructions

Separate instructions for source vs. test files:

<!-- source-code.instructions.md -->
---
applyTo: "src/**/*.ts"
---
Production code guidelines...
<!-- test-code.instructions.md -->
---
applyTo: "**/*.test.ts,**/*.spec.ts"
---
Test code guidelines:
- Use descriptive test names: `test('should calculate total when given valid items', ...)`
- Follow AAA pattern: Arrange, Act, Assert
- Mock external dependencies

Pattern 5: Tool-Driven Instructions

Guide Copilot to use specific tools for certain operations:

---
applyTo: "src/**/*.tsx"
---

# React Component Guidelines

## Before Creating New Components
Use #tool:codebase to search for similar components:
1. Check if component already exists
2. Find reusable patterns in existing components
3. Ensure naming consistency with existing components

## Before Modifying Components
Use #tool:usages to check component usage:
- Verify changes won't break existing uses
- Consider creating new component for breaking changes

🧪 Testing and Validation

How to Test Instruction Files

Instructions are invisible, making testing indirect. Here’s how to validate them:

1. Check the References List

When using Copilot Chat in VS Code, expand the References list at the top of responses. Instruction files that matched your current file will be listed.

Screenshot showing References list with instruction files

2. Test with Specific File Types

  1. Open a file that should match your applyTo pattern
  2. Ask Copilot to generate code relevant to your instructions
  3. Check if generated code follows your guidelines

Example test:

<!-- File: .github/instructions/python-naming.instructions.md -->
---
applyTo: "**/*.py"
---
Always use snake_case for function names and variables.

Test: Open a .py file, ask Copilot: “Create a function that calculates total price with tax”

Expected: Function named calculate_total_price_with_tax, not calculateTotalPriceWithTax

3. Test with Conflicting Instructions

Deliberately create overlapping patterns to verify Copilot handles them gracefully:

<!-- test-conflict-1.instructions.md -->
---
applyTo: "test/**/*.py"
---
Prefix test functions with `test_`
<!-- test-conflict-2.instructions.md -->
---
applyTo: "**/*.py"
---
Use descriptive function names

Open test/test_user.py, ask for a test. Verify both instructions are honored: test_user_authentication_succeeds_with_valid_credentials()

4. Verify excludeAgent Works

<!-- coding-agent-only.instructions.md -->
---
applyTo: "**/*.py"
excludeAgent: "code-review"
---
[specific guidelines]

Test by:

  1. Using Copilot coding agent (should apply instructions)
  2. Using Copilot code review (should NOT apply instructions)

Validation Checklist

Before committing instruction files, verify:

💡 Decision Framework

Use this flowchart to decide whether to use instruction files or alternatives:

START: Need to provide guidance to Copilot?
│
├─ Is this guidance specific to certain file types/locations?
│  │
│  YES─ Will this guidance be used repeatedly?
│  │    │
│  │    YES─ Is the guidance < 500 lines?
│  │    │    │
│  │    │    YES─ ✅ USE INSTRUCTION FILE
│  │    │    │
│  │    │    NO─ ⚠️  SPLIT INTO MULTIPLE INSTRUCTION FILES
│  │    │
│  │    NO─ Is this a one-time task?
│  │        │
│  │        YES─ ✅ USE PROMPT FILE or INLINE CHAT
│  │        │
│  │        NO─ ✅ USE PROMPT FILE (reusable task)
│  │
│  NO─ Is this defining a persona or role?
│      │
│      YES─ ✅ USE AGENT FILE
│      │
│      NO─ Is this general project info?
│          │
│          YES─ ✅ USE .github/copilot-instructions.md
│          │
│          NO─ ❓ RECONSIDER: Maybe not needed?

Quick Reference Table

Need Solution File Type
TypeScript coding standards Instruction file typescript-standards.instructions.md
Generate React form component Prompt file create-react-form.prompt.md
Security reviewer persona Agent file security-reviewer.agent.md
General project architecture Repository instructions .github/copilot-instructions.md
One-time code refactoring Chat command Inline chat or /explain, /fix commands
Multi-step workflow Agent file or Prompt file Depends on reusability

🎯 Conclusion

Instruction files are a powerful but subtle tool for shaping Copilot’s behavior. When used correctly, they ensure consistent coding standards across your project without manual intervention. When used poorly, they consume context, create confusion, and introduce unpredictable behavior.

Key takeaways:

  1. Be specific with applyTo patterns - Avoid broad patterns like **
  2. Keep instructions concise and actionable - Focus on “how”, not “why”
  3. Avoid conflicts between instruction files - Make each file self-contained
  4. Test with actual file types - Verify instructions apply correctly
  5. Monitor context consumption - Multiple files add up quickly
  6. Use the right tool for the job - Instructions aren’t always the answer

By following these guidelines, you’ll create instruction files that enhance Copilot’s effectiveness without introducing unwanted side effects.


📚 References

Official Documentation

GitHub: Adding Repository Custom Instructions [📘 Official]
Official GitHub documentation for creating repository-level custom instructions including .github/copilot-instructions.md and path-specific .instructions.md files. Covers frontmatter syntax, glob patterns, and the excludeAgent property. Essential reference for understanding how GitHub interprets instruction files across different platforms (VS Code, Visual Studio, GitHub.com).

VS Code: Use Custom Instructions [📘 Official]
Microsoft’s official documentation for custom instructions in VS Code. Explains the three types of instruction files (.github/copilot-instructions.md, .instructions.md, and AGENTS.md), how they’re combined, and provides examples of effective instruction structures. Includes details on user-scope vs. workspace-scope instructions and Settings Sync.

VS Code: Copilot Customization Overview [📘 Official]
Comprehensive overview of all Copilot customization options in VS Code, including instructions, prompts, and agents. Explains how different customization types work together and when to use each. Critical for understanding the broader context of instruction files within the customization ecosystem.

Best Practices and Community Resources

GitHub Blog: How to Use GitHub Copilot - Tips, Tricks, and Best Practices [📗 Verified Community]
GitHub’s official blog post on maximizing Copilot effectiveness through context management. While focused on general Copilot usage, provides crucial insights on how context (including instructions) impacts suggestion quality. Explains the “context, context, context” principle that applies to instruction file design.

Awesome GitHub Copilot Repository [📗 Verified Community]
Community-curated collection of Copilot customizations including example instruction files. Browse the /instructions directory for real-world examples across different languages and frameworks. Demonstrates practical patterns for instruction file organization and content structure.

GitHub Blog: Prompting with GitHub Copilot [📗 Verified Community]
Official guide to prompt engineering with Copilot. While focused on prompts, the principles of clarity, specificity, and context apply equally to instruction files. Essential reading for understanding how to write effective guidance for LLMs.